#pragma once

#include "StateObject.h"
#include "DataFormat.h"

namespace FlameEngine
{
	enum GraphicsResourceUsage
	{
		gru_default,	//gpu read/write
		gru_immutable,	//gpu read
		gru_dynamic,	//gpu read,cpu write
		gru_staging,	//gpu read/write, cpu read/write
	};

	enum GraphicsResourceBindFlag:uint8_t
	{
		grb_vertexBuffer		= 0x001,
		grb_indexBuffer			= 0x002,
		grb_constantBuffer		= 0x004,
		grb_shaderResource		= 0x008,
		grb_streamOutput		= 0x010,
		grb_renderTarget		= 0x020,
		grb_unorderedAccess		= 0x040
	};

	enum GraphicsResourceMiscFlag:uint8_t
	{
		grmf_generateMipmap		= 0x0001,
		grmf_shared				= 0x0002,
		grmf_textureCube		= 0x0004,
		grmf_drawIndirectArgs	= 0x0008,
		grmf_bufferAllowRawView = 0x0010,
		grmf_bufferStructured	= 0x0020,
		grmf_resourceClamp		= 0x0040,
		grmf_sharedKeyedMutex	= 0x0080,
		grmf_gdiCompatible		= 0x0100,
	};

	struct BufferDesc
	{
		GraphicsResourceUsage usage;
		GraphicsResourceBindFlag bindFlag;
		GraphicsResourceMiscFlag miscFlag;
		int32_t size;
	};

	class GrphicsBuffer
	{
	public:
		GrphicsBuffer(BufferDesc& pDesc, void* pData);
		virtual ~GrphicsBuffer();

		const BufferDesc& GetDesc() const { return m_desc;}
		
	protected:
		BufferDesc m_desc;
	};


	class IGraphicsDeviceContext
	{
	public:
		virtual void Begin() = 0;
		virtual void End() = 0;

		virtual void ClearRenderTarget() = 0;
		virtual void ClearDepthTarget() = 0;
		virtual void ClearState() = 0;

		virtual void DrawIndexed() = 0;
		virtual void DrawIndexedBuffered() = 0;
		virtual void DrawIndexedInstanced() = 0;

		virtual void SetDepthStencilState(const DepthStencilState* dsState) = 0;
		virtual void SetBlendState(const BlendState* bsState) = 0;
		virtual void SetRasterizerState(const RasterizerState* rastState) = 0;
		virtual void SetRenderTarget() = 0;
		virtual void SetSissorRect() = 0;
		virtual void SetViewports() = 0;

		virtual void SetVertexBuffers() = 0;
		virtual void SetIndexBuffer() = 0;
		virtual void SetInputLayout() = 0;

		virtual void VSSetShader() = 0;
		virtual void VSSetSamplers(uint32_t startSlot,SamplerState* state,uint32_t samplerCount) = 0;
		virtual void VSSetConstantBuffer() = 0;
		virtual void VSSetTexture() = 0;

		virtual void GSSetShader() = 0;
		virtual void GSSetSamplers(uint32_t startSlot,SamplerState* state,uint32_t samplerCount) = 0;
		virtual void GSSetConstantBuffer() = 0;
		virtual void GSSetTexture() = 0;

		virtual void PSSetShader() = 0;
		virtual void PSSetSamplers(uint32_t startSlot,SamplerState* state,,uint32_t samplerCount) = 0;
		virtual void PSSetConstantBuffer() = 0;
		virtual void PSSetTexture() = 0;

		virtual void DSSetShader() = 0;
		virtual void DSSetSamplers(uint32_t startSlot,SamplerState* state,uint32_t samplerCount,) = 0;
		virtual void DSSetConstantBuffer() = 0;
		virtual void DSSetTexture() = 0;

		virtual void HSSetShader() = 0;
		virtual void HSSetSamplers(uint32_t startSlot,uint32_t samplerCount,SamplerState* state) = 0;
		virtual void HSSetConstantBuffer() = 0;
		virtual void HSSetTexture() = 0;

		virtual void Draw() = 0;
		virtual void DrawAuto() = 0;
		virtual void DrawIndexed() = 0;
		virtual void DrawIndexedInsatanced() = 0;
		virtual void DrawIndexedInsatancedIndirect() = 0;

		virtual bool IsDefferedContext() = 0;
	};

	class IGraphicsResourceFactory
	{
		//state
		virtual BlendState* CreateBlendState() = 0;
		virtual DepthStencilState* CreateDepthStencilState() = 0;
		virtual RasterizerState* CreateRasterizerState() = 0;
		virtual SamplerState* CreateSamplerState() = 0;

		//resource
		virtual void CreaetInputLayout() = 0; 
		virtual void CreateBuffer() = 0;
		virtual void CreateTexture1D() = 0;
		virtual void CreateTexture2D() = 0;
		virtual void CreateTexture3D() = 0;
		virtual void CreateQuery() = 0;
		virtual void CreatePredicate() = 0;

		//shader
		virtual void CreateVertexShader() = 0;			
		virtual void CreateGeometryShader() = 0;
		virtual void CreateHullShader() = 0;
		virtual void CreateDomainShader() = 0; 
		virtual void CreateComputerShader() = 0;

		//
	}
}